<?php

namespace app\common\command;

use payment\{WorldFirstService, AirwallexService, SlashService};
use think\console\Command;
use think\console\Input;
use think\console\Output;
use app\common\model\card\Card;
use think\facade\Log;

class UpdateCard extends Command
{
    protected function configure()
    {
        $this->setName('update_card')
            ->setDescription('更新卡资料');
    }

    protected function execute(Input $input, Output $output)
    {
        // 创建锁文件
        $lockFile = runtime_path() . 'lock/update_card.lock';
        $lockDir = dirname($lockFile);

        // 确保锁目录存在
        if (!is_dir($lockDir)) {
            mkdir($lockDir, 0755, true);
        }

        // 尝试获取文件锁
        $fp = fopen($lockFile, 'w+');
        if (!$fp) {
            // 使用 trace() 函数记录错误，这个更可靠
            trace('无法创建锁文件: ' . $lockFile, 'error');
            return false;
        }

        // 尝试获取独占锁
        if (!flock($fp, LOCK_EX | LOCK_NB)) {
            Log::channel('card_update')->info('任务正在执行中，跳过本次执行');
            fclose($fp);
            return false;
        }

        try {
            // 写入进程ID和时间戳
            $lockInfo = [
                'pid' => getmypid(),
                'start_time' => date('Y-m-d H:i:s'),
                'memory_usage' => memory_get_usage(true)
            ];
            ftruncate($fp, 0);
            fwrite($fp, json_encode($lockInfo));
            fflush($fp);

            Log::channel('card_update')->info('开始执行卡片更新命令');

            //查询万里付卡
            $worldFirstCards = Card::where('card_bin', 10)
                ->where('secure_msg', NULL)
                ->select()->toArray();

            Log::channel('card_update')->info('查询到万里付卡片数量: ' . count($worldFirstCards));
            $worldFirstSuccess = 0;
            $worldFirstFail = 0;
            $worldFirst = new WorldFirstService('worldfirst');
            foreach ($worldFirstCards as $card) {
                if ($this->worldfirst($card, $worldFirst)) {
                    $worldFirstSuccess++;
                } else {
                    $worldFirstFail++;
                }
            }
            Log::channel('card_update')->info("万里付卡处理完成 - 成功: {$worldFirstSuccess}, 失败: {$worldFirstFail}");

            //查询香港万里付卡
            $worldFirstCards = Card::where('card_bin', 13)
                ->where('secure_msg', NULL)
                ->select()->toArray();
//            dump($worldFirstCards);

            Log::channel('card_update')->info('查询到香港万里付卡片数量: ' . count($worldFirstCards));
            $worldFirstSuccess = 0;
            $worldFirstFail = 0;
            $worldFirst = new WorldFirstService('worldfirst_hk');
            foreach ($worldFirstCards as $card) {
                if ($this->worldfirst($card, $worldFirst)) {
                    $worldFirstSuccess++;
                } else {
                    $worldFirstFail++;
                }
            }
            Log::channel('card_update')->info("香港万里付卡处理完成 - 成功: {$worldFirstSuccess}, 失败: {$worldFirstFail}");

            //空中云付敏感信息处理
            $airwallexCards = Card::where('card_bin', 11)
                ->where('secure_msg', NULL)
                ->select()->toArray();

            Log::channel('card_update')->info('查询到空中云付卡片数量: ' . count($airwallexCards));

            $airwallexSuccess = 0;
            $airwallexFail = 0;
            foreach ($airwallexCards as $card) {
                if ($this->airwallex($card)) {
                    $airwallexSuccess++;
                } else {
                    $airwallexFail++;
                }
            }
            Log::channel('card_update')->info("空中云付卡处理完成 - 成功: {$airwallexSuccess}, 失败: {$airwallexFail}");

            //slash敏感信息处理
            $slashCards = Card::whereIn('card_bin', [12, 15])
                ->where('secure_msg', null)
                ->select()->toArray();

            Log::channel('card_update')->info('查询到slash卡片数量: ' . count($slashCards));

            $slashCreateSuccess = 0;
            $slashCreateFail = 0;
            foreach ($slashCards as $card) {
                if ($this->slash_create($card)) {
                    $slashCreateSuccess++;
                } else {
                    $slashCreateFail++;
                }
            }
            Log::channel('card_update')->info("slash开卡处理完成 - 成功: {$slashCreateSuccess}, 失败: {$slashCreateFail}");

            sleep(5);
            //敏感信息查看，服务端是异步，所以这里开卡后sleep 5秒
            $slashCards = Card::whereIn('card_bin', [12, 15])
                ->where('secure_msg', null)
                ->select()->toArray();

            Log::channel('card_update')->info('查询到需要获取敏感信息的slash卡片数量: ' . count($slashCards));

            $slashSecureSuccess = 0;
            $slashSecureFail = 0;
            foreach ($slashCards as $card) {
                if ($this->slash_secure($card)) {
                    $slashSecureSuccess++;
                } else {
                    $slashSecureFail++;
                }
            }
            Log::channel('card_update')->info("slash敏感信息处理完成 - 成功: {$slashSecureSuccess}, 失败: {$slashSecureFail}");

            $output->writeln("所有卡片处理完成");
            Log::channel('card_update')->info('卡片更新命令执行完成');

            // 更新锁文件信息，记录完成时间
            $lockInfo['end_time'] = date('Y-m-d H:i:s');
            $lockInfo['status'] = 'completed';
            ftruncate($fp, 0);
            fwrite($fp, json_encode($lockInfo));
            fflush($fp);

            return true;

        } catch (\Exception $e) {
            Log::channel('card_update')->error('卡片更新命令执行失败: ' . $e->getMessage());

            // 更新锁文件信息，记录错误状态
            $lockInfo['end_time'] = date('Y-m-d H:i:s');
            $lockInfo['status'] = 'error';
            $lockInfo['error'] = $e->getMessage();
            ftruncate($fp, 0);
            fwrite($fp, json_encode($lockInfo));
            fflush($fp);

            return false;

        } finally {
            // 释放锁并关闭文件
            flock($fp, LOCK_UN);
            fclose($fp);
        }
    }

    //更新万里付卡
    private function worldfirst($card, $worldFirst)
    {
        try {
            Log::channel('worldfirst')->info('开始处理万里付卡片: ' . $card['card_nick_name']);

            //开卡
            $worldFirstResult = $worldFirst->applyCard(['card_nickname' => $card['card_nick_name']]);
            Log::channel('worldfirst')->info('万里付开卡请求');
            Log::channel('worldfirst')->info(json_encode($worldFirstResult));
//            dump($worldFirstResult);
            if ($worldFirstResult['result']['resultStatus'] != 'S') {
                Log::channel('worldfirst')->error('万里付卡开卡失败: ' . $worldFirstResult['result']['resultMessage']);
                return false;
            }

            sleep(1);
            //查卡
            $worldFirstResult = $worldFirst->getCardList(['card_nick_name' => $card['card_nick_name']]);
            Log::channel('worldfirst')->info('万里付查卡请求');
            Log::channel('worldfirst')->info(json_encode($worldFirstResult));
//            dump($worldFirstResult);

            if ($worldFirstResult['result']['resultStatus'] != 'S') {
                Log::channel('worldfirst')->error('查询卡片列表失败: ' . $worldFirstResult['result']['resultMessage']);
                return false;
            }

            //万里付卡返回的卡id
            $cardId = $worldFirstResult['cardList'][0]['assetId'];
            Log::channel('worldfirst')->info('获取到万里付卡片ID: ' . $cardId);

            //查看敏感信息
            sleep(1);
            $worldFirstResult = $worldFirst->getCardSensitiveInfo($cardId);
//            dump($worldFirstResult);
            Log::channel('worldfirst')->info('万里付获取敏感信息');
            Log::channel('worldfirst')->info(json_encode($worldFirstResult));

            if ($worldFirstResult['result']['resultStatus'] != 'S') {
                Log::channel('worldfirst')->error('查看敏感信息失败: ' . $worldFirstResult['result']['resultMessage']);
                return false;
            }

            $cardSecure = json_encode([
                'card_num' => $worldFirstResult['cardNo'],
                'cvv' => $worldFirstResult['cvv'],
                'expiry_month' => $worldFirstResult['expiredMonth'],
                'expiry_year' => $worldFirstResult['expiredYear'],
            ]);
            $secureMsg = encrypt($cardSecure);

            // 更新数据库
            $updateData = [
                'card_id' => $cardId,
                'card_no' => $worldFirstResult['cardNo'],
                'secure_msg' => $secureMsg,
                'update_time' => time(),
            ];

            Card::where('card_nick_name', $card['card_nick_name'])->update($updateData);

            Log::channel('worldfirst')->info('数据库更新成功 - 卡号: ' . $worldFirstResult['cardNo']);

            //万里付卡限额处理
            if ($card['single_transaction_limit'] > 0 && $card['daily_transaction_limit'] > 0 && $card['monthly_transaction_limit'] > 0) {
                sleep(1);
                $limitData = [
                    'asset_id' => $cardId,
                    'per_transaction_limit_max' => $card['single_transaction_limit'] * 100,
                    'daily_limit_max' => $card['daily_transaction_limit'] * 100,
                    'monthly_limit_max' => $card['monthly_transaction_limit'] * 100,
                    'per_card_limit_max' => $card['total_transaction_limit'] * 100,
                ];

                Log::channel('worldfirst')->info('开始设置万里付卡片限额');
                Log::channel('worldfirst')->info(json_encode($limitData));

                $worldFirstResult = $worldFirst->updateCardLimit($limitData);

                if ($worldFirstResult['result']['resultStatus'] != 'S') {
                    Log::channel('worldfirst')->error('万里付卡限额处理失败: ' . $worldFirstResult['result']['resultMessage']);
                    return false;
                }

                Log::channel('worldfirst')->info('万里付卡片限额设置成功');
            } else {
                Log::channel('worldfirst')->info('万里付卡片无需设置限额');
            }
            return true;

        } catch (\Exception $e) {
            Log::channel('worldfirst')->error('万里付卡片处理异常: ' . $e->getMessage());
            return false;
        }
    }

    private function airwallex($card)
    {
        try {
            Log::channel('airwallex')->info('开始处理空中云付卡片: ' . $card['card_id']);

            $airwallex = new AirwallexService();
            $airwallexResult = $airwallex->getCardDetail($card['card_id']);

            Log::channel('airwallex')->info('空中云付获取卡片详情');
            Log::channel('airwallex')->info(json_encode($airwallexResult));

            if (!isset($airwallexResult['card_number'])) {
                Log::channel('airwallex')->error('查询卡片详情失败: ' . ($airwallexResult['message'] ?? '未知错误'));
                return false;
            }

            $cardSecure = json_encode([
                'card_num' => $airwallexResult['card_number'],
                'cvv' => $airwallexResult['cvv'],
                'expiry_month' => $airwallexResult['expiry_month'],
                'expiry_year' => $airwallexResult['expiry_year'],
            ]);

            $secureMsg = encrypt($cardSecure);

            // 更新数据库
            $updateData = [
                'card_no' => $airwallexResult['card_number'],
                'secure_msg' => $secureMsg,
                'update_time' => time(),
            ];

            Card::where('card_id', $card['card_id'])->update($updateData);

            Log::channel('airwallex')->info('空中云付卡片处理成功 - 卡号: ' . $airwallexResult['card_number']);
            return true;

        } catch (\Exception $e) {
            Log::channel('airwallex')->error('空中云付卡片处理异常: ' . $e->getMessage());
            return false;
        }
    }

    //slash卡创建
    private function slash_create($card)
    {
        try {
            Log::channel('slash')->info('开始处理slash卡片: ' . $card['card_nick_name']);

            $slashService = new SlashService($card['card_bin']);

            $result = $slashService->createCard($card['card_nick_name']);
            Log::channel('slash')->info('slash开卡请求');
            Log::channel('slash')->info(json_encode($result));

            if (!isset($result['id'])) {
                Log::channel('slash')->error('slash开卡失败');
                Log::channel('slash')->error(json_encode($result));
                return false;
            }
            $cardId = $result['id'];

            Log::channel('slash')->info('slash开卡成功，获取到卡片ID: ' . $cardId);

            //限额处理优先级:总>月>天
            $limit = 0;
            $preset = 'daily';
            $single_transaction_limit = $card['single_transaction_limit'] ?? '0';
            $daily_transaction_limit = $card['daily_transaction_limit'] ?? '0';
            $monthly_transaction_limit = $card['monthly_transaction_limit'] ?? '0';
            $total_transaction_limit = $card['total_transaction_limit'] ?? '0';

            if ($daily_transaction_limit) {
                $preset = 'daily';
                $limit = $daily_transaction_limit;
            }
            if ($monthly_transaction_limit) {
                $preset = 'monthly';
                $limit = $monthly_transaction_limit;
            }
            if ($total_transaction_limit) {
                $preset = 'collective';
                $limit = $total_transaction_limit;
            }

            if ($limit) {
                Log::channel('slash')->info('开始设置slash卡片限额 - 限额类型: ' . $preset . ' - 限额金额: ' . $limit);
                //注意，这里是美分，所以*100
                $slashService->setCardRule($cardId, $preset, $limit * 100, $single_transaction_limit * 100);
                Log::channel('slash')->info('slash卡片限额设置成功');
            } else {
                Log::channel('slash')->info('slash卡片无需设置限额');
            }

            $new = [
                'card_id' => $cardId,
                'update_time' => time(),
            ];
            Card::where('card_id', $card['card_id'])->update($new);

            Log::channel('slash')->info('slash开卡成功，数据库更新完成 - 新卡片ID: ' . $cardId);
            return true;

        } catch (\Exception $e) {
            Log::channel('slash')->error('slash开卡异常: ' . $e->getMessage());
            return false;
        }
    }

    //卡号加密信息查看
    private function slash_secure($card)
    {
        try {
            Log::channel('slash')->info('开始获取slash卡片敏感信息 - 卡片: ' . $card['card_id']);

            $slashService = new SlashService($card['card_bin']);
            $result = $slashService->getCardInfo($card['card_id'], true);

            Log::channel('slash')->info('slash获取卡片信息');
            Log::channel('slash')->info(json_encode($result));

            if (isset($result['pan']) && $result['pan']) {
                $cardSecure = json_encode([
                    'card_num' => $result['pan'],
                    'cvv' => $result['cvv'],
                    'expiry_month' => $result['expiryMonth'],
                    'expiry_year' => $result['expiryYear'],
                ]);

                Card::where('card_id', $card['card_id'])
                    ->update(['card_no' => $result['pan'], 'secure_msg' => encrypt($cardSecure)]);

                Log::channel('slash')->info('slash敏感信息处理成功 - 卡号: ' . $result['pan']);
                return true;
            } else {
                Log::channel('slash')->error('slash获取卡片信息失败 - 返回数据中缺少卡号信息');
                return false;
            }
        } catch (\Exception $e) {
            Log::channel('slash')->error('slash敏感信息处理异常: ' . $e->getMessage());
            return false;
        }
    }
}